package com.seeingtv.common.utils;


import org.apache.log4j.Logger;

import java.net.NetworkInterface;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.Date;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * @author hubert
 * @date 2017-11-11
 * */
public class IDGenerateUtils {
    private static Logger log = Logger.getLogger(IDGenerateUtils.class);


    private static Date startDate =  SafeUtils.safeGetDate("20171001");

    private static AtomicInteger idIntger = new AtomicInteger(0);


    /**
     * 生成唯一ID，位数随时间递增
     * */
    public static long getNextIdByIP() {
        if (idIntger.get() >= 999) {
            idIntger.set(0);
        }
        String id = "000"+idIntger.getAndIncrement();
        id=id.substring(id.length()-3, id.length());
        return  SafeUtils.getLong((System.currentTimeMillis()-startDate.getTime()) + "" +SafeUtils.getLocalIPFlag()+ ""+ id);
    }

    /**
     * 生成唯一ID，位数随时间递增
     * */
    public static long getNextIdByMac() {
        if (idIntger.get() >= 1000) {
            idIntger.set(0);
        }
        System.out.println(getMachineIdentifier());
        String mac = "000" + getMachineIdentifier();
        mac = mac.substring(mac.length()-2,mac.length());

        String id = "000"+idIntger.getAndIncrement();
        id=id.substring(id.length()-3, id.length());
        return  SafeUtils.getLong((System.currentTimeMillis()-startDate.getTime())  +mac + id);
    }


    /**
     * 生成唯一ID：18位
     * 生成规则：时间戳(10位)+机器码(3位)+进程id(2位)+计数器（3位）
     * 借鉴MongoDB的ObjectID生成规则，<version>3.4.2</version>
     * @return long
     * */
    public static long getNextIdByMacPid() {

        Date date = new Date();
        long time = date.getTime();

        String mac = "000" + getMachineIdentifier();
        mac = mac.substring(mac.length()-3,mac.length());

        String pid = "00"+ (time&getProcessIdentifier());
        pid = pid.substring(pid.length()-2,pid.length());
        if (idIntger.get() >= 1000) {
            idIntger.set(1);
        }
        String id= "000"+idIntger.getAndIncrement();
        id=id.substring(id.length()-3, id.length());
        return  SafeUtils.getLong( time/1000 + mac + pid + id);
    }


    /**
     * 获取机器唯一标识
     * */
    private static int getMachineIdentifier() {
        int machinePiece;
        try {
            StringBuilder sb = new StringBuilder();
            Enumeration e = NetworkInterface.getNetworkInterfaces();

            while(e.hasMoreElements()) {
                NetworkInterface ni = (NetworkInterface)e.nextElement();
                sb.append(ni.toString());
                byte[] mac = ni.getHardwareAddress();
                if (mac != null) {
                    ByteBuffer bb = ByteBuffer.wrap(mac);
                    try {
                        sb.append(bb.getChar());
                        sb.append(bb.getChar());
                        sb.append(bb.getChar());
                    } catch (BufferUnderflowException var7) {
                        log.error(var7.getMessage(),var7);
                    }
                }
            }
            machinePiece = sb.toString().hashCode();
        } catch (Throwable var8) {
            machinePiece = (new SecureRandom()).nextInt();
            log.error( "Failed to get machine identifier from network interface, using random number instead", var8);
        }
        machinePiece &= 16777215;
        return machinePiece;
    }

    /**
     * 获取进程ID
     * */
    private static int getProcessIdentifier() {
        int processId;
        try {
            String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
            if (processName.contains("@")) {
                processId =  Integer.parseInt(processName.substring(0, processName.indexOf('@')));
            } else {
                processId =  java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();
            }

        } catch (Throwable t) {
            processId = new SecureRandom().nextInt();
            log.error("Failed to get process identifier from JMX, using random number instead", t);
        }

        return processId;
    }

    @Override
    public String toString(){
        return "success";
    }

    public static void main(String[] args) {
        IDGenerateUtils idGenerate = new IDGenerateUtils();
        System.out.println(idGenerate);

        for (int i = 0; i <20000 ; i++) {
            //System.out.println(getNextIdByMac());
            //System.out.println(getNextIdByIP());
            System.out.println(getNextIdByMacPid());
        }
    }
}
